#include "sphere.h"

#include <cstdio>
#include <cmath>

#include <glm/gtc/constants.hpp>
namespace ShaderLab {
	Sphere::Sphere(float radius, GLuint nSlices, GLuint nStacks)
	{
		int nVerts = (nSlices + 1) * (nStacks + 1);
		int elements = (nSlices * 2 * (nStacks - 1)) * 3;

		// Verts
		std::vector<GLfloat> vertices(3 * nVerts);
		// Normals
		std::vector<GLfloat> normals(3 * nVerts);
		// texCoord coords
		std::vector<GLfloat> texCoord(2 * nVerts);
		// Elements
		std::vector<GLuint> indices(elements);

		// Generate positions and normals
		GLfloat theta, phi;
		GLfloat thetaFac = glm::two_pi<float>() / nSlices;
		GLfloat phiFac = glm::pi<float>() / nStacks;
		GLfloat nx, ny, nz, s, t;
		GLuint idx = 0, tIdx = 0;
		for (GLuint i = 0; i <= nSlices; i++) {
			theta = i * thetaFac;
			s = (GLfloat)i / nSlices;
			for (GLuint j = 0; j <= nStacks; j++) {
				phi = j * phiFac;
				t = (GLfloat)j / nStacks;
				nx = sinf(phi) * cosf(theta);
				ny = sinf(phi) * sinf(theta);
				nz = cosf(phi);
				vertices[idx] = radius * nx; vertices[idx + 1] = radius * ny; vertices[idx + 2] = radius * nz;
				normals[idx] = nx; normals[idx + 1] = ny; normals[idx + 2] = nz;
				idx += 3;

				texCoord[tIdx] = s;
				texCoord[tIdx + 1] = t;
				tIdx += 2;
			}
		}

		// Generate the element list
		idx = 0;
		for (GLuint i = 0; i < nSlices; i++) {
			GLuint stackStart = i * (nStacks + 1);
			GLuint nextStackStart = (i + 1) * (nStacks + 1);
			for (GLuint j = 0; j < nStacks; j++) {
				if (j == 0) {
					indices[idx] = stackStart;
					indices[idx + 1] = stackStart + 1;
					indices[idx + 2] = nextStackStart + 1;
					idx += 3;
				}
				else if (j == nStacks - 1) {
					indices[idx] = stackStart + j;
					indices[idx + 1] = stackStart + j + 1;
					indices[idx + 2] = nextStackStart + j;
					idx += 3;
				}
				else {
					indices[idx] = stackStart + j;
					indices[idx + 1] = stackStart + j + 1;
					indices[idx + 2] = nextStackStart + j + 1;
					indices[idx + 3] = nextStackStart + j;
					indices[idx + 4] = stackStart + j;
					indices[idx + 5] = nextStackStart + j + 1;
					idx += 6;
				}
			}
		}

		initBuffers(&indices, &vertices, &normals, &texCoord);
	}

}